home *** CD-ROM | disk | FTP | other *** search
- // Copyright (c)1995 Ray Dream, Inc. All Rights Reserved.
- /* $Id: COMFog.cpp 1.4 1997/04/10 00:53:01 damien Exp $ */
-
- ////////////////////////////////////////////////////////////////////////
- // AtmosphericShader Example : Atmos //
- //--------------------------------------------------------------------//
- // Implementation of the Atmos Interface //
- ////////////////////////////////////////////////////////////////////////
-
- #include "math.h"
-
- #ifndef __COMFOG__
- #include "COMFOG.h"
- #endif
-
- #ifndef __FOGDLL__
- #include "FOGDLL.h"
- #endif
-
- // Failure Handling
- #ifndef __3DCOFAIL__
- #include "3DCoFail.h"
- #endif
-
- #undef INTERFACE
- #define INTERFACE Atmos
- // Constructor / Destructor of the C++ Object :
- Atmos::Atmos() {
- fCRef=0; // Reference Counter
- // Data initialisation :
- fData.fColor.Mode=0; // White
- fData.fColor.R=1.0;
- fData.fColor.G=1.0;
- fData.fColor.B=1.0;
- fData.fZmin=0.0; // from 0 to 20"
- fData.fZmax=5.0;
- fData.fVisibility=10.0;
- }
-
- Atmos::~Atmos() {
- global_count_Obj--;
- }
-
- // IUnknown Interface :
- HRESULT Atmos::QueryInterface(THIS_ REFIID riid,LPVOID* ppvObj) {
- *ppvObj=NULL;
-
- // The Atmos knows the interfaces of the parent Objects
- if (IsEqualIID(riid, IID_IUnknown))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExAtmosphericShader))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExDataExchanger))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExtension))
- *ppvObj=(LPVOID)this;
-
- // we must add reference if we return an interface
- if (*ppvObj!=NULL) {
- ((LPUNKNOWN)*ppvObj)->AddRef();
- return NOERROR;
- }
- else {
- return ResultFromScode(E_NOINTERFACE);
- }
- }
-
- ULONG Atmos::AddRef(THIS) {
- return fCRef++;
- }
-
- ULONG Atmos::Release(THIS) {
- ULONG UnreleaseObject=fCRef--;
-
- if (fCRef==0)
- delete this; // No reference left, so destroy the object
-
- return UnreleaseObject;
- // local variable used, because fCRef can be destroyed before.
- }
-
- // I3DExtension methods :
- I3DExtension* Atmos::Clone(THIS) {
- Atmos* theClone = new Atmos;
- if (theClone) {
- theClone->AddRef();
- theClone->fData=fData; // copy the AtmosData
- }
- return theClone;
- }
-
- HRESULT Atmos::ShellUtilitiesInit(THIS_ IShUtilities* shellUtilities) {
- InitCoFailure(shellUtilities);
- return NOERROR;
- }
-
- // I3DExDataExchanger methods :
- ExtensionDataMap* Atmos::GetExtensionDataMap(THIS) {
- return NULL;
- }
-
- void* Atmos::GetExtensionDataBuffer(THIS) {
- return &fData; // used by the shell to set the new parameters
- }
-
- HRESULT Atmos::ExtensionDataChanged(THIS) {
- return NOERROR;
- }
-
- HRESULT Atmos::HandleEvent(THIS_ ULONG SourceID) {
- return ResultFromScode(E_NOTIMPL);
- }
-
- short Atmos::GetResID(THIS) {
- return 134; // this is the view ID in the resource file.
- }
-
- // I3DExAtmosphericShader methods :
- HRESULT Atmos::SegmentFilter(THIS_ VECTOR3D* beg, VECTOR3D* end, COLOR3D* filterOut) {
- NUM3D distanceInTheFog;
- VECTOR3D beamVector;
- VECTOR3D beaminfogbeg,beaminfogend;
- NUM3D filtercoef,colorcoef;
- if (((*beg)[2]>fData.fZmax)&&((*end)[2]>fData.fZmax)) { // the light beam is above the fog
- // Don't do anything
- }
- else if (((*beg)[2]<fData.fZmin)&&((*end)[2]<fData.fZmin)) { // the light beam is under the fog
- // Don't do anything
- }
- else { // The Light beam crosses the fog
- if ((*beg)[2]>fData.fZmax) {
- beaminfogbeg[2]=fData.fZmax;
- beaminfogbeg[0]=(*beg)[0]+((*end)[0]-(*beg)[0])/((*end)[2]-(*beg)[2])*(fData.fZmax-(*beg)[2]);
- beaminfogbeg[1]=(*beg)[1]+((*end)[1]-(*beg)[1])/((*end)[2]-(*beg)[2])*(fData.fZmax-(*beg)[2]);
- }
- else if ((*beg)[2]<fData.fZmin) {
- beaminfogbeg[2]=fData.fZmin;
- beaminfogbeg[0]=(*beg)[0]+((*end)[0]-(*beg)[0])/((*end)[2]-(*beg)[2])*(fData.fZmin-(*beg)[2]);
- beaminfogbeg[1]=(*beg)[1]+((*end)[1]-(*beg)[1])/((*end)[2]-(*beg)[2])*(fData.fZmin-(*beg)[2]);
- }
- else {
- beaminfogbeg[0]=(*beg)[0];
- beaminfogbeg[1]=(*beg)[1];
- beaminfogbeg[2]=(*beg)[2]; // the begining point of the light beam is in the fog
- }
- if ((*end)[2]>fData.fZmax) {
- beaminfogend[2]=fData.fZmax;
- beaminfogbeg[0]=(*beg)[0]+((*end)[0]-(*beg)[0])/((*end)[2]-(*beg)[2])*(fData.fZmax-(*beg)[2]);
- beaminfogbeg[1]=(*beg)[1]+((*end)[1]-(*beg)[1])/((*end)[2]-(*beg)[2])*(fData.fZmax-(*beg)[2]);
- }
- else if ((*end)[2]<fData.fZmin) {
- beaminfogend[2]=fData.fZmin;
- beaminfogend[0]=(*beg)[0]+((*end)[0]-(*beg)[0])/((*end)[2]-(*beg)[2])*(fData.fZmin-(*beg)[2]);
- beaminfogend[1]=(*beg)[1]+((*end)[1]-(*beg)[1])/((*end)[2]-(*beg)[2])*(fData.fZmin-(*beg)[2]);
- }
- else {
- beaminfogend[0]=(*end)[0];
- beaminfogend[1]=(*end)[1];
- beaminfogend[2]=(*end)[2]; // the ending point of the light beam is in the fog
- }
- beamVector[0]=beaminfogend[0]-beaminfogbeg[0];
- beamVector[1]=beaminfogend[1]-beaminfogbeg[1];
- beamVector[2]=beaminfogend[2]-beaminfogbeg[2];
- distanceInTheFog=sqrt(SQR(beamVector[0]) + SQR(beamVector[1]) + SQR(beamVector[2]));
- filtercoef=1.0-distanceInTheFog/fData.fVisibility;
- if (filtercoef<0.0) {
- filtercoef=0.0;
- }
- colorcoef=1.0-filtercoef;
- filterOut->R=filterOut->R*filtercoef+fData.fColor.R*colorcoef;
- filterOut->G=filterOut->G*filtercoef+fData.fColor.G*colorcoef;
- filterOut->B=filterOut->B*filtercoef+fData.fColor.B*colorcoef;
- }
- return NOERROR;
- }
-
-
- HRESULT Atmos::DirectionFilter(THIS_ VECTOR3D* origin, VECTOR3D* direction, COLOR3D* filterOut) {
- NUM3D distanceInTheFog;
- VECTOR3D beamVector;
- VECTOR3D beaminfogbeg,beaminfogend;
- NUM3D filtercoef,colorcoef;
-
- if (((*origin)[2]>fData.fZmax)&&((*direction)[2]>=0.0)) {
- // Don't do anything
- }
- else if (((*origin)[2]<fData.fZmin)&&((*direction)[2]<=0.0)) {
- // Don't do anything
- }
- else {
- if (((*origin)[2]>fData.fZmax)||((*origin)[2]<fData.fZmin)) {
- beaminfogbeg[2]=fData.fZmax;
- beaminfogbeg[0]=(*origin)[0]+(*direction)[0]*(fData.fZmax-(*origin)[2])/(*direction)[2];
- beaminfogbeg[1]=(*origin)[1]+(*direction)[1]*(fData.fZmax-(*origin)[2])/(*direction)[2];
- beaminfogend[2]=fData.fZmin;
- beaminfogend[0]=(*origin)[0]+(*direction)[0]*(fData.fZmin-(*origin)[2])/(*direction)[2];
- beaminfogend[1]=(*origin)[1]+(*direction)[1]*(fData.fZmin-(*origin)[2])/(*direction)[2];
- }
- else if ((*direction)[2]>0.0) {
- beaminfogbeg[0]=(*origin)[0];
- beaminfogbeg[1]=(*origin)[1];
- beaminfogbeg[2]=(*origin)[2];
- beaminfogend[2]=fData.fZmax;
- beaminfogend[0]=(*origin)[0]+(*direction)[0]*(fData.fZmax-(*origin)[2])/(*direction)[2];
- beaminfogend[1]=(*origin)[1]+(*direction)[1]*(fData.fZmax-(*origin)[2])/(*direction)[2];
- }
- else if ((*direction)[2]<0.0) {
- beaminfogbeg[0]=(*origin)[0];
- beaminfogbeg[1]=(*origin)[1];
- beaminfogbeg[2]=(*origin)[2];
- beaminfogend[2]=fData.fZmin;
- beaminfogend[0]=(*origin)[0]+(*direction)[0]*(fData.fZmin-(*origin)[2])/(*direction)[2];
- beaminfogend[1]=(*origin)[1]+(*direction)[1]*(fData.fZmin-(*origin)[2])/(*direction)[2];
- }
- else { // (*direction)[2]=0.0
- *filterOut=fData.fColor;
- return NOERROR;
- }
- beamVector[0]=beaminfogend[0]-beaminfogbeg[0];
- beamVector[1]=beaminfogend[1]-beaminfogbeg[1];
- beamVector[2]=beaminfogend[2]-beaminfogbeg[2];
- distanceInTheFog=sqrt(SQR(beamVector[0]) + SQR(beamVector[1]) + SQR(beamVector[2]));
- filtercoef=1.0-distanceInTheFog/fData.fVisibility;
- if (filtercoef<0.0) {
- filtercoef=0.0;
- }
- colorcoef=1.0-filtercoef;
- filterOut->R=filterOut->R*filtercoef+fData.fColor.R*colorcoef;
- filterOut->G=filterOut->G*filtercoef+fData.fColor.G*colorcoef;
- filterOut->B=filterOut->B*filtercoef+fData.fColor.B*colorcoef;
- }
- return NOERROR;
- }
-
-